# PE Grammar for PE Grammars
# 
# Adapted from [1] by Ian Piumarta <first-name at last-name point com>.
# 
# Local modifications (marked '#ikp') to support:
#     C text in '{ ... }' copied verbatim to output as 'semantic action'
#     input consumed between '<' and '>' is 'char yytext[]' in semantic actions
# 
# Best viewed using 140 columns monospaced with tabs every 8.
# 
# [1] Bryan Ford.  "Parsing Expression Grammars: A Recognition-Based Syntactic
#     Foundation."  Symposium on Principles of Programming Languages,
#     January 14--16, 2004, Venice, Italy.
# 
# Last edited: 2016-07-15 10:27:27 by piumarta on zora

# Hierarchical syntax

Grammar		<- Spacing Definition+ EndOfFile

Definition	<- Identifier 			{ if (push(beginRule(findRule(yytext)))->rule.expression) fprintf(stderr, "rule '%s' redefined\n", yytext); }
		     LEFTARROW Expression	{ Node *e= pop();  Rule_setExpression(pop(), e); } &{ YYACCEPT }
Expression	<- Sequence (SLASH Sequence	{ Node *f= pop();  push(Alternate_append(pop(), f)); }
			    )*
Sequence	<- Prefix (Prefix		{ Node *f= pop();  push(Sequence_append(pop(), f)); }	#ikp expanded from 'Seq <- Prefix*'
			  )*
		 / 				{ push(makePredicate("1")); }				#ikp added
Prefix		<- AND Action			{ push(makePredicate(yytext)); }	#ikp added
		 / AND Suffix			{ push(makePeekFor(pop())); }		#ikp expanded from 'Prefix <- (AND/NOT)? Suffix'
		 / NOT Suffix			{ push(makePeekNot(pop())); }
		 /     Suffix
Suffix		<- Primary (QUESTION		{ push(makeQuery(pop())); }
			     / STAR		{ push(makeStar (pop())); }
			     / PLUS		{ push(makePlus (pop())); }
			   )?
Primary		<- Identifier !LEFTARROW	{ push(makeName(findRule(yytext))); }
		 / OPEN Expression CLOSE
		 / Literal			{ push(makeString(yytext)); }
		 / Class			{ push(makeClass(yytext)); }
		 / DOT				{ push(makeDot()); }
		 / Action			{ push(makeAction(0, yytext)); }	#ikp added
		 / BEGIN			{ push(makePredicate("YY_BEGIN")); }	#ikp added
		 / END				{ push(makePredicate("YY_END")); }	#ikp added

# Lexical syntax

Identifier	<- < IdentStart IdentCont* > Spacing		#ikp inserted < ... >
IdentStart	<- [a-zA-Z_]
IdentCont	<- IdentStart / [0-9]
Literal		<- ['] < (!['] Char )* > ['] Spacing		#ikp inserted < ... >
		 / ["] < (!["] Char )* > ["] Spacing		#ikp inserted < ... >
Class		<- '[' < (!']' Range)* > ']' Spacing		#ikp inserted < ... >
Range		<- Char '-' Char / Char
Char		<- '\\' [abefnrtv'"\[\]\\]			#ikp added missing ANSI escapes: abefv
		 / '\\' [0-3][0-7][0-7]
		 / '\\' [0-7][0-7]?
		 / '\\' '-'					#ikp added
		 / !'\\' .
LEFTARROW	<- '<-' Spacing
SLASH		<- '/' Spacing
AND		<- '&' Spacing
NOT		<- '!' Spacing
QUESTION	<- '?' Spacing
STAR		<- '*' Spacing
PLUS		<- '+' Spacing
OPEN		<- '(' Spacing
CLOSE		<- ')' Spacing
DOT		<- '.' Spacing
Spacing		<- (Space / Comment)*
Comment		<- '#' (!EndOfLine .)* EndOfLine
Space		<- ' ' / '\t' / EndOfLine
EndOfLine	<- '\r\n' / '\n' / '\r'
EndOfFile	<- !.

Action		<- '{' < [^}]* > '}' Spacing		#ikp added
BEGIN		<- '<' Spacing				#ikp added
END		<- '>' Spacing				#ikp added
